Fix a multi HVM domain issue (bugzilla bug #542):
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Tue, 28 Feb 2006 09:18:34 +0000 (10:18 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Tue, 28 Feb 2006 09:18:34 +0000 (10:18 +0100)
        This issue can be reproduced on SMP platform, while the domain 0
is UP. The reason is, after finishing a dma request, the dma thread will
trigger the interrupt and then clear the call back function. When guest
get the interrupt , it will try to check the call back function, if it
is set, then it will trigger a dma request again. So if the checking for
the callbackfunction happens between trigger interrupt and clear
callback function on dma thread, it will cause NULL function calling.
After with domain 0 UP and smp platform, this situation can be
reproduced easily.

Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
tools/ioemu/hw/ide.c

index 7c012cebcb8bd7d371785102a38553c56d32dc04..7ed0815da6c4c51df6d548098a7f4fbff8a65669 100644 (file)
@@ -669,9 +669,6 @@ static int ide_read_dma_cb(IDEState *s,
     }
     if (s->io_buffer_index >= s->io_buffer_size && s->nsector == 0) {
         s->status = READY_STAT | SEEK_STAT;
-        s->bmdma->status &= ~BM_STATUS_DMAING;
-        s->bmdma->status |= BM_STATUS_INT;
-        ide_set_irq(s);
 #ifdef DEBUG_IDE_ATAPI
         printf("dma status=0x%x\n", s->status);
 #endif
@@ -738,9 +735,6 @@ static int ide_write_dma_cb(IDEState *s,
             if (n == 0) {
                 /* end of transfer */
                 s->status = READY_STAT | SEEK_STAT;
-                s->bmdma->status &= ~BM_STATUS_DMAING;
-                s->bmdma->status |= BM_STATUS_INT;
-                ide_set_irq(s);
                 return 0;
             }
             if (n > MAX_MULT_SECTORS)
@@ -987,9 +981,6 @@ static int ide_atapi_cmd_read_dma_cb(IDEState *s,
     if (s->packet_transfer_size <= 0) {
         s->status = READY_STAT;
         s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
-        s->bmdma->status &= ~BM_STATUS_DMAING;
-        s->bmdma->status |= BM_STATUS_INT;
-        ide_set_irq(s);
 #ifdef DEBUG_IDE_ATAPI
         printf("dma status=0x%x\n", s->status);
 #endif
@@ -2025,6 +2016,17 @@ static void ide_map(PCIDevice *pci_dev, int region_num,
     }
 }
 
+static void ide_dma_finish(BMDMAState *bm)
+{
+    IDEState *s = bm->ide_if;
+
+    bm->status &= ~BM_STATUS_DMAING;
+    bm->status |= BM_STATUS_INT;
+    bm->dma_cb = NULL;
+    bm->ide_if = NULL;
+    ide_set_irq(s);
+}
+
 /* XXX: full callback usage to prepare non blocking I/Os support -
    error handling */
 #ifdef DMA_MULTI_THREAD
@@ -2070,9 +2072,8 @@ static void ide_dma_loop(BMDMAState *bm)
         cur_addr += 8;
     }
     /* end of transfer */
- the_end:
-    bm->dma_cb = NULL;
-    bm->ide_if = NULL;
+the_end:
+    ide_dma_finish(bm);
 }
 
 static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb)